\documentclass[a4paper,spanish]{article}

\input{preambulo}

\hyphenation{ob-te-ner}

\begin{document}

\input{caratula}

\tableofcontents

\pagebreak

\section{Int'erprete}
Este trabajo se realiz'o utilizando el ambiente Pharo 1.4\\
(\texttt{http://gforge.inria.fr/frs/download.php/30621/Pharo-1.4-14438-OneClick.zip}).

\section{Clase Tipo}

\begin{lstlisting}
Object subclass: #Tipo
	instanceVariableNames: 'nombre efectividad'
	classVariableNames: 'Todos'
	poolDictionaries: ''
	category: 'TP3'!
\end{lstlisting}

\subsection{M'etodos de instancia}

\begin{lstlisting}
efectividadContra: unNombre
	"devuelve la efectividad de este tipo contra uno de nombre unNombre"

	^efectividad at: unNombre ifAbsent: 1
\end{lstlisting}

\begin{lstlisting}
nombre
	^nombre
\end{lstlisting}

\begin{lstlisting}
nombre: unNombre
	"El nombre de un tipo se puede establecer una sola vez, para mantener consistencia del diccionario Todos."
	nombre isNil
		ifTrue: [nombre := unNombre]
\end{lstlisting}

\begin{lstlisting}
efectividad: unNumero contra: unNombre
	"establece la efectividad de este tipo contra tipos de nombre unNombre"

	(#(0 0.5 1 2) includes: unNumero)
		ifTrue: [efectividad at: unNombre put: unNumero].
	^self
\end{lstlisting}

\begin{lstlisting}
= unTipo
	^self nombre = (unTipo nombre)
\end{lstlisting}

\begin{lstlisting}
initialize
	efectividad := Dictionary new
\end{lstlisting}

\subsection{M'etodos de clase}

\begin{lstlisting}
initialize
	"self initialize"

	Todos := Dictionary new
\end{lstlisting}

\begin{lstlisting}
existeTipo: unNombre
	"true sii ya existe un tipo de nombre unNombre"

	^Todos includesKey: unNombre
\end{lstlisting}

\begin{lstlisting}
cargarTiposIniciales
	| datos nombres |
	nombres := #('Normal' 'Fuego' 'Agua' 'Planta' 'Fantasma').
	datos := Dictionary new
		at: 'Normal' put: #(1 1 1 1 0);
		at: 'Fuego' put: #(1 0.5 0.5 2 1);
		at: 'Agua' put: #(1 2 0.5 0.5 1);
		at: 'Planta' put: #(1 0.5 2 0.5 1);
		at: 'Fantasma' put: #(0 1 1 1 2);
		yourself.
	datos keysAndValuesDo: [ :nombre :valores |
		| tipo |
		tipo := Tipo new: nombre.
		1 to: (nombres size) do: [ :i |
			tipo efectividad: (valores at: i) contra: (nombres at: i)
		]
	]
\end{lstlisting}

\begin{lstlisting}
new: unNombre
	"si existe, devuelve el tipo de nombre unNombre; si no, crea un nuevo tipo de nombre unNombre"

 	(Todos includesKey: unNombre)
		ifTrue: [ ^Todos at: unNombre ]
		ifFalse: [ ^Todos at: unNombre put: ((self new) nombre: unNombre)]
\end{lstlisting}

\section{Clase Pokemon}

\begin{lstlisting}
Object subclass: #Pokemon
	instanceVariableNames: 'nombre nivel energia'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'TP3'
\end{lstlisting}

\begin{lstlisting}
Pokemon class
	instanceVariableNames: 'Ataque_base Defensa_base Energia_base Tipo_pokemon'
\end{lstlisting}


\subsection{M'etodos de instancia}


\begin{lstlisting}
curar: unValor
	energia := energia + unValor > (self energiaTotal) ifTrue: [self energiaTotal] ifFalse: [self energiaTotal + energia]
\end{lstlisting}


\begin{lstlisting}
herir: unValor
	energia := energia < unValor ifTrue: [0] ifFalse: [energia - unValor]
\end{lstlisting}



\begin{lstlisting}
initialize: unNombre
	nivel := 1.
	nombre := unNombre.
	energia := self class energiaBase
\end{lstlisting}



\begin{lstlisting}
ataque
	^(self class ataqueBase * 2 + 94) * (self nivel / 100.0) + 5
\end{lstlisting}

\begin{lstlisting}
defensa
	^(self class defensaBase * 2 + 94) * (self nivel / 100.0) + 5
\end{lstlisting}

\begin{lstlisting}
energia 
	^energia
\end{lstlisting}

\begin{lstlisting}
energiaTotal
	^(self class energiaBase * 2 + 94) * (self nivel / 100.0) + 10 + (self nivel)
\end{lstlisting}

\begin{lstlisting}
nivel 
	^nivel
\end{lstlisting}


\begin{lstlisting}
nombre 
	^nombre
\end{lstlisting}


\begin{lstlisting}
tipo 
	^self class tipo
\end{lstlisting}



\begin{lstlisting}
subirNivel
	nivel < 100 ifTrue: [nivel := nivel + 1]
\end{lstlisting}



\begin{lstlisting}
atacarA: oponente conPoder: poder deTipo: unTipo
	| danho multXTipo |
	(oponente energia = 0 or: (self energia = 0)) ifTrue: [^self].
	
	multXTipo := unTipo efectividadContra: oponente tipo nombre.
	self tipo = unTipo ifTrue: [multXTipo := multXTipo * 1.5].
	danho := self nivel * 2 / 5.0 + 2 * (self ataque) * poder / (oponente defensa) / 50.0 + 2 * multXTipo.
	oponente herir: danho.
	oponente energia = 0 ifTrue: [self subirNivel]
\end{lstlisting}

\subsection{M'etodos de clase}


\begin{lstlisting}
ataqueBase
	^Ataque_base
\end{lstlisting}


\begin{lstlisting}
ataqueBase: unNumero
	Ataque_base := unNumero
\end{lstlisting}


\begin{lstlisting}
defensaBase
	^Defensa_base
\end{lstlisting}


\begin{lstlisting}
defensaBase: unNumero
	Defensa_base := unNumero
\end{lstlisting}


\begin{lstlisting}
energiaBase
	^Energia_base
\end{lstlisting}


\begin{lstlisting}
energiaBase: unNumero
	Energia_base := unNumero
\end{lstlisting}


\begin{lstlisting}
tipo
	^Tipo_pokemon
\end{lstlisting}


\begin{lstlisting}
tipo: unTipo
	Tipo_pokemon := unTipo
\end{lstlisting}



\begin{lstlisting}
crearClasesDePrueba
	Pokemon eliminarSubclases;
				nuevaEspecie: #Ninetales conTipo: 'Fuego' energiaBase: 73 ataqueBase: 81 defensaBase: 100;
				nuevaEspecie: #Bellossom conTipo: 'Planta' energiaBase: 75 ataqueBase: 90 defensaBase: 100;
				nuevaEspecie: #Mismagius conTipo: 'Fantasma' energiaBase: 60 ataqueBase: 105 defensaBase: 105;
				nuevaEspecie: #Stoutland conTipo: 'Normal' energiaBase: 85 ataqueBase: 100 defensaBase: 90;
				nuevaEspecie: #Wailord conTipo: 'Agua' energiaBase: 170 ataqueBase: 90 defensaBase: 45
\end{lstlisting}


\begin{lstlisting}
eliminarSubclases 
	Pokemon subclassesDo: [:s | s removeFromSystem]
\end{lstlisting}


\begin{lstlisting}
nuevaEspecie: nombreEspecie conTipo: nombreTipo energiaBase: eb ataqueBase: ab defensaBase: db
	| class |
	class := self subclass: (nombreEspecie asSymbol) instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: (self category asString).
	self addSubclass: class. "Para que la clase salga listada en Pokemon subclasses"
	class class compile: '
	new: unNombre
	^self new initialize: unNombre'.
	class energiaBase: eb;
			ataqueBase: ab;
			defensaBase: db;
			tipo: (Tipo new: nombreTipo)
\end{lstlisting}

\section{Tests}

\subsection{Clase Tipo}

\begin{lstlisting}
TestCase subclass: #TipoTest
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'TP3-tests'
\end{lstlisting}


\begin{lstlisting}
setUp
	"Me aseguro de que no haya ning'un tipo creado antes de empezar los tests"

	Tipo initialize
\end{lstlisting}


\begin{lstlisting}
tearDown
	"Vuelo todos los tipos que pueden haber creado los tests"

	Tipo initialize
\end{lstlisting}


\begin{lstlisting}
testEfectividad
	|tipo|
	tipo := Tipo new: 'tipo'.
	self assert: 1 equals: (tipo efectividadContra: 'otro tipo'). 
	tipo efectividad: 2 contra: 'otro tipo'.
	self assert: 2 equals: (tipo efectividadContra: 'otro tipo'). 
	tipo efectividad: 19 contra: 'otro tipo'.
	self assert: 2 equals: (tipo efectividadContra: 'otro tipo')
\end{lstlisting}


\begin{lstlisting}
testExisteTipo
	Tipo new: 'un tipo'.
	self assert: (Tipo existeTipo: 'un tipo')
\end{lstlisting}


\begin{lstlisting}
testNombre
	|tipo|
	tipo := Tipo new: 'nombre loco'.
	self assert: (tipo nombre = 'nombre loco')
\end{lstlisting}


\begin{lstlisting}
testSingletonidad
	"Testea que si cre'as dos tipos con el mismo nombre te d'e la misma instancia"

	self assert: ((Tipo new: 'bla') == (Tipo new: 'bla'))
\end{lstlisting}


\subsection{Clase Pokemon}

\begin{lstlisting}
TestCase subclass: #PokemonTest
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'TP3-tests'!
\end{lstlisting}


\begin{lstlisting}
setUp
	Pokemon crearClasesDePrueba.
	Tipo cargarTiposIniciales
\end{lstlisting}


\begin{lstlisting}
testAtaqueADesmayado
	"El ataque a un desmayado no se produce. Usamos que el atacante no cambia de nivel como prueba de que el ataque no se hizo."

	| atacante victima |
	atacante := (self subclass: 'Ninetales') new: 'atacante ninetal'.
	victima := (self subclass: 'Bellossom') new: 'victima bellossom'.
	victima herir: (victima energia).
	atacante atacarA: victima conPoder: 1 deTipo: (Tipo new: 'Agua').
	self assert: 1 equals: atacante nivel
\end{lstlisting}


\begin{lstlisting}
testAtaqueDeDesmayado
	"Un ataque hecho por un desmayado no se produce. Usamos que la energ'ia de la v'ictima no cambia como prueba de que el ataque no se hizo."

	| atacante victima energiaPrevia |
	atacante := (self subclass: 'Ninetales') new: 'atacante ninetal'.
	victima := (self subclass: 'Bellossom') new: 'victima bellossom'.
	atacante herir: (atacante energia).
	energiaPrevia := victima energia.
	atacante atacarA: victima conPoder: 1 deTipo: (Tipo new: 'Agua').
	self assert: energiaPrevia equals: victima energia
\end{lstlisting}

\begin{lstlisting}
testAtaqueFuegoConAgua
	"Un pokemon especie Ninetales (tipo fuego) ataca a un Bellossom (tipo planta) con ataque tipo agua"
	"Ejercita el multiplicador por tipo 1"

	| atacante victima |
	atacante := (self subclass: 'Ninetales') new: 'atacante ninetal'.
	victima := (self subclass: 'Bellossom') new: 'victima bellossom'.
	atacante atacarA: victima conPoder: 1 deTipo: (Tipo new: 'Agua').
	self assert: ((victima energia - 73.98) abs < 0.1)
\end{lstlisting}

\begin{lstlisting}
testAtaqueFuegoConFuego
	"Un pokemon especie Ninetales (tipo fuego) ataca a un Bellossom (tipo planta) con ataque tipo fuego"
	"Ejercita el multiplicador por tipo 1.5"

	| atacante victima |
	atacante := (self subclass: 'Ninetales') new: 'atacante ninetal'.
	victima := (self subclass: 'Bellossom') new: 'victima bellossom'.
	atacante atacarA: victima conPoder: 1 deTipo: (Tipo new: 'Fuego').
	self assert: ((victima energia - 68.86) abs < 0.1)
\end{lstlisting}


\begin{lstlisting}
testAtaqueSubirNivel
	"Un pokemon que le da la estocada final a otro debe subir de nivel."

	| atacante victima |
	atacante := (self subclass: 'Ninetales') new: 'atacante ninetal'.
	victima := (self subclass: 'Bellossom') new: 'victima bellossom'.
	victima herir: (victima energia - 5).
	atacante atacarA: victima conPoder: 1 deTipo: (Tipo new: 'Fuego').
	self assert: 2 equals: atacante nivel
\end{lstlisting}


\begin{lstlisting}
testNombre
	"Las subclases de Pokemon responden al mensaje new: nombre"

	| pokemon |
	pokemon := (self subclass: 'Ninetales') new: 'nombre loco'.
	self assert: 'nombre loco' equals: pokemon nombre
\end{lstlisting}



\begin{lstlisting}
subclass: unNombre
	"Devuelve la instancia actual de la subclase de Pokemon de nombre unNombre."
	"Esto es necesario porque cada vez que se corren los tests se eliminan y vuelven a crear
	todas las subclases, haciendo imposible que se harcodeen los nombres de las clases en
	los mensajes de test."

	Pokemon subclassesDo: [:s | s name = unNombre ifTrue: [^s]]
\end{lstlisting}

\end{document}
